<template>
  <BasicDrawer
    v-bind="$attrs"
    @register="registerDrawer"
    showFooter
    :title="formTitle"
    width="40%"
    @ok="handleSaveChanges"
    :maskClosable="false"
    :destroyOnClose="true"
    @close="closeFunc"
  >
    <!-- v-model:value="model[field]" -->
    <BasicForm @register="registerForm" class="pr-3" ref="formElRef" autoComplete="off">
      <!-- {model, field} -->
      <template #menu="{}">
        <BasicTree
          title="菜单分配"
          checkable
          toolbar
          showLine
          :value="checkedAllKeysRef"
          :treeData="state.treeData"
          :fieldNames="{ title: 'name', key: 'id' }"
          :onCheck="onCheck"
          :checkedKeys="state.treeCheckedKeys"
        />
      </template>
    </BasicForm>
  </BasicDrawer>
</template>
<script lang="ts" setup>
  import { ref, unref, reactive, watch } from 'vue';
  import { BasicForm, useForm, FormActionType } from '@/components/Form';
  import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  import { BasicTree, TreeItem } from '@/components/Tree';
  import _ from 'lodash';

  import { useMessage } from '@/hooks/web/useMessage';
  import { useI18n } from '@/hooks/web/useI18n';

  import { getSelectMenu } from '@/api/system/menu';
  import { Role } from '@/api/system/model/roleModel';
  import { useRoleDrawer } from './hook/useRoleDrawer';
  import { StateEntity } from './datas/roleDrawerData';

  const { createMessage } = useMessage();
  const { t } = useI18n();
  const isUpdate = ref(true);
  const emit = defineEmits(['success', 'register']);
  let childArr: number[] = []; // 存放所有子节点的数组

  const roleRef = ref<Nullable<Role>>(null);
  const formElRef = ref<Nullable<FormActionType>>(null);
  const { formTitle, formSchemas, handleSubmit } = useRoleDrawer({ roleRef, formElRef });

  const state = reactive<StateEntity>({
    roleId: 0,
    treeData: [],
    checkedMenu: [],
    treeCheckedKeys: [],
    menuCheckedKeys: [],
  });

  const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
    resetFields();
    setDrawerProps({ confirmLoading: false });
    isUpdate.value = !!data?.isUpdate;
    roleRef.value = data.record;
    state.roleId = data.record?.id; // 角色ID

    // 需要在setFieldsValue之前先填充treeData，否则Tree组件可能会报key not exist警告
    if (!state.treeData.length) {
      state.treeData = (await getSelectMenu()) as unknown as TreeItem[];
    }

    if (unref(isUpdate)) {
      // 获取到所有的子节点
      getChildAll(state.treeData);
      state.checkedMenu = data.record['menu'];
      state.treeCheckedKeys = _.intersection(childArr, state.checkedMenu);
      state.menuCheckedKeys = data.record['menu'];

      setFieldsValue({
        ...data.record,
      });
    }
  });

  const [registerForm, { resetFields, setFieldsValue, validate, getFieldsValue, updateSchema }] =
    useForm({
      labelWidth: 50,
      baseColProps: { span: 24 },
      schemas: formSchemas,
      showActionButtonGroup: false,
    });

  function getChildAll(data: TreeItem[]) {
    data.map((res) => {
      if (res.children && res.children.length > 0) {
        getChildAll(res.children);
      } else {
        childArr.push(res['id']);
      }
    });
    return childArr;
  }

  const checkedAllKeysRef = ref<any>([]);

  let checkedAllKeys: number[] = [];
  function onCheck(checkedKeys: number[], e: any) {
    checkedAllKeys = _.intersection(checkedAllKeys, checkedKeys);
    checkedAllKeys = _.union(checkedKeys, checkedAllKeys, e.halfCheckedKeys);
  }

  function handleSaveChanges() {
    setDrawerProps({ confirmLoading: true });
    validate()
      .then(() => {
        let fieldsValue = getFieldsValue();
        fieldsValue['id'] = roleRef.value?.id;
        if (checkedAllKeys.length) {
          fieldsValue['menu'] = _.sortBy(_.union(checkedAllKeys));
        } else {
          fieldsValue['menu'] = _.sortBy(state.menuCheckedKeys);
        }
        handleSubmit(fieldsValue)
          .then(() => {
            createMessage.success(t('sys.api.operationSuccess'));
            state.roleId = 0;
            emit('success');
            closeDrawer();
          })
          .catch((err) => {
            createMessage.error(err);
          })
          .finally(() => {});
      })
      .finally(() => {
        setDrawerProps({ confirmLoading: false });
      });
  }

  watch(
    () => state.roleId,
    (roleId) => {
      if (roleId == 0 || roleId == undefined) {
        state.checkedMenu = [];
        state.menuCheckedKeys = [];
        state.treeCheckedKeys = [];
        childArr = [];
        checkedAllKeys = [];
      }
    },
    {
      immediate: true,
    },
  );

  function closeFunc() {
    state.roleId = 0;
  }
</script>
